﻿using System;
using System.Collections.Generic;
using System.Linq;
using Ue.CQRS.Bus;
using Ue.CQRS.Configuration;
using Ue.CQRS.DistributionManager;
using Ue.CQRS.Repositories;
using Ue.CQRS.Results;

namespace Ue.CQRS.Events
{
    /// <summary>
    /// 事件源（即：发布事件的对象）
    /// 记录某个事件源对象所有发布过的历史事件，相当于一个Event Store（事件存储器）
    /// </summary>
    public class EventSource<TSender> : IEventSource
    {
        private IBus bus;
        private IEventRepository eventRepository;
        private IConfiguration settings;
        //自己的事件分发
        private IDistributor distributor;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bus">事件总线</param>
        /// <param name="repository">事件存储器</param>
        /// <param name="name">事件源名称</param>
        /// <param name="sender">发布事件的对象</param>
        internal EventSource(IConfiguration configuration, IBus bus,
            IEventRepository eventRepository,
            string name,
            TSender sender)
        {
            this.bus = bus;
            this.settings = configuration;
            this.eventRepository = eventRepository;

            this.Name = name;
            this.Sender = sender;
        } 

        /// <summary>
        /// 事件源名称，默认是事件源对象的Type.Name
        /// </summary>
        public string Name { get; private set; }

        /// <summary> 
        /// 事件源对象
        /// </summary>
        public TSender Sender { get; private set; }

        /// <summary>
        /// 版本
        /// </summary>
        public long Version { get; private set; }

        /// <summary>
        /// 发布事件
        /// </summary>
        /// <param name="domainEvent"></param>
        /// <param name="eventArg"></param>
        public void RaiseEvent(IEvent @event)
        {
            if (@event == null)
            {
                throw new ArgumentNullException("事件不能为null");
            }

            if (this.settings.EnabledEventStore)
            {
                this.eventRepository.Add(@event);
            }

 
            this.distributor.Dispatch(@event);
            this.bus.Send(@event);
        }
    }
}
